#include <Engine/StdAfx.h>
#include <Engine/SceneGraph/BVSphere.h>
#include <Engine/SceneGraph/Transformation.h>

using namespace fastbird;

BoundingVolume* BoundingVolume::Create(BVType type /*= BV_SPHERE*/)
{
	return new BVSphere;
}

//----------------------------------------------------------------------------
BVSphere::BVSphere()
{
}

//----------------------------------------------------------------------------
BVSphere::BVSphere(const Vec3& center, float radius)
	: mCenter(center), mRadius(radius)
{
}

//----------------------------------------------------------------------------
void BVSphere::ComputeFromData(const Vec3* pVertices, size_t numVertices)
{
	assert(pVertices && numVertices>0);
	mCenter = pVertices[0];
	for (size_t i=1; i<numVertices; i++)
	{
		mCenter+=pVertices[i];
	}
	mCenter /= (float)numVertices;
	mRadius = 0;
	for (size_t i=0; i<numVertices; i++)
	{
		Vec3 diff = pVertices[i] - mCenter;
		float radiusSQ = diff.LengthSQ();
		if (radiusSQ > mRadius)
		{
			mRadius = radiusSQ;
		}
	}
	mRadius = sqrt(mRadius);
}

//----------------------------------------------------------------------------
void BVSphere::TransformBy(const Transformation& transform,
			BoundingVolume* result)
{
	assert(result);
	BVSphere* pNewSphere = (BVSphere*)result;
	Vec3 newCenter = transform.ApplyForward(mCenter);
	float newRadius = transform.GetNorm() * mRadius;
	pNewSphere->SetCenter(newCenter);
	pNewSphere->SetRadius(newRadius);
}

//----------------------------------------------------------------------------
int BVSphere::WhichSide(const Plane3& plane) const
{
	float fDistance = plane.DistanceTo(mCenter);

    if (fDistance <= -mRadius)
    {
        return -1;
    }

    if (fDistance >= mRadius)
    {
        return +1;
    }

    return 0;
}

//----------------------------------------------------------------------------
bool BVSphere::TestIntersection(const Ray3& ray) const
{
	assert(0 && "Not Implemented!");
	return false;
}